'''
Description: 
Author: notplus
Date: 2021-12-12 17:19:21
LastEditors: notplus
LastEditTime: 2021-12-14 19:11:17
FilePath: /change_detection.py

Copyright (c) 2021 notplus
'''

import pickle
import numpy as np
from numpy.core.fromnumeric import sort
from pyproj import Transformer
import matplotlib.pyplot as plt
from sklearn.cluster import DBSCAN
from datetime import datetime, timedelta

import utils
from extra_stay_points import ActivityCluster, User, Trajectory, StayPoint
from dbscan import DBSCAN

THRESHOLD = 0.9

def detect_obsolete(activities, t_end):
    n = len(activities)
    if n == 1:
        return False
    else:
        sum_ta = 0
        activities.sort(key=lambda rec: rec.arv_t)
        for i in range(n-1):
            sum_ta += (activities[i+1].arv_t - activities[i].arv_t).total_seconds()
        t_int = sum_ta / (n - 1)
        D_t = (t_end - activities[-1].arv_t).total_seconds()
        if D_t > t_int:
            return True
        else:
            return False


with open('all_activity_cluster_128.pickle', 'rb') as f:
    all_activity_cluster = pickle.load(f)

num_cluster = len(all_activity_cluster)
# D = np.zeros((num_cluster, num_cluster))
new_activity_cluster = all_activity_cluster.copy()

for i in range(num_cluster):
    tmp_activity_cluster_index = []
    for j in range(i + 1, num_cluster):
        # a_stay_duration = (all_activity_cluster[i].lev_t - all_activity_cluster[i].arv_t).total_seconds()
        a_stay_duration = all_activity_cluster[i].duration
        a_arv_t = (all_activity_cluster[i].arv_t).total_seconds()
        a = a_stay_duration * a_arv_t

        # b_stay_duration = (all_activity_cluster[j].lev_t - all_activity_cluster[j].arv_t).total_seconds()
        b_stay_duration = all_activity_cluster[j].duration
        b_arv_t = (all_activity_cluster[j].arv_t).total_seconds()
        b = b_stay_duration * b_arv_t

        c_stay_duration = min(a_stay_duration, b_stay_duration)
        c_arv_t = min(a_arv_t, b_arv_t)
        c = c_stay_duration * c_arv_t

        D = c / (a + b - c)

        ai_c_stay_duration = 1e10
        ai_c_arv_t = 1e10

        sum_ai = 0

        for ait in all_activity_cluster[i].activities:
            ai_stay_duration = (ait.lev_t - ait.arv_t).total_seconds()
            ai_arv_t = (ait.arv_t - ait.arv_t.replace(hour=0,
                        minute=0, second=0, microsecond=0)).total_seconds()
            sum_ai += ai_stay_duration * ai_arv_t

            ai_c_stay_duration = min(ai_c_stay_duration, ai_stay_duration)
            ai_c_arv_t = min(ai_c_arv_t, ai_arv_t)

        ai_c = ai_c_stay_duration * ai_c_arv_t

        d_1 = ai_c / \
            (sum_ai - (len(all_activity_cluster[i].activities) - 1) * ai_c)

        ai_c_stay_duration = 1e10
        ai_c_arv_t = 1e10

        sum_ai = 0

        for ait in all_activity_cluster[j].activities:
            ai_stay_duration = (ait.lev_t - ait.arv_t).total_seconds()
            ai_arv_t = (ait.arv_t - ait.arv_t.replace(hour=0,
                        minute=0, second=0, microsecond=0)).total_seconds()
            sum_ai += ai_stay_duration * ai_arv_t

            ai_c_stay_duration = min(ai_c_stay_duration, ai_stay_duration)
            ai_c_arv_t = min(ai_c_arv_t, ai_arv_t)

        ai_c = ai_c_stay_duration * ai_c_arv_t

        d_2 = ai_c / \
            (sum_ai - (len(all_activity_cluster[j].activities) - 1) * ai_c)
        
        d = max(d_1, d_2)
        # d = 0.8

        if d == 1:
            d = THRESHOLD
        
        if D > d:
            print('similar activity!')
            tmp_activity_cluster_index.append(j)
            # new_activity_cluster.append(ActivityCluster(
            #     all_activity_cluster[i].activities+all_activity_cluster[j].activities))

        else:
            # if not detect_obsolete(all_activity_cluster[i].activities, datetime(2011, 7, 1)):
            #     new_activity_cluster.append(all_activity_cluster[i])

            # if not detect_obsolete(all_activity_cluster[j].activities, datetime(2011, 7, 1)):
            #     new_activity_cluster.append(all_activity_cluster[j])
            pass

    if len(tmp_activity_cluster_index) == 0:
        if detect_obsolete(all_activity_cluster[i].activities, datetime(2011, 7, 1)):
            # new_activity_cluster.append(all_activity_cluster[i])
            # new_activity_cluster.pop(i)
            # new_activity_cluster.remove(all_activity_cluster[i])
            new_activity_cluster[i] = None
    else:
        tmp_activity_cluster = []
        for act_idx in tmp_activity_cluster_index:
            tmp_activity_cluster.append(all_activity_cluster[act_idx])
        
        tmp_activity_cluster.sort(key=lambda act: act.activities[-1].arv_t)
        
        for act_idx in tmp_activity_cluster_index:
            new_activity_cluster[act_idx].lat, new_activity_cluster[act_idx].lng = tmp_activity_cluster[-1].lat, tmp_activity_cluster[-1].lng 
        # new_activity_cluster.append(tmp_activity_cluster[-1])
        
new_activity_cluster = list(filter(None, new_activity_cluster))
new_activity_cluster.sort(key = lambda act : len(act.activities),reverse=True)

with open('new_activity_cluster_128.pickle', 'wb') as f:
    pickle.dump(new_activity_cluster, f)
